<script setup lang="ts">
  import mapConfig from './mapConfig';
  import iconUrl from './icon-focus.png';

  /*
  接收数据：地图相关的配置 customMapConfig、点位详情中的点击事件 gisHTMLLinkClick
  暴露出 addPointLayer 方法、 addPolylineLayer 、 clearMapLayer 方法、
  */
  interface IObject {
    [name: string]: any;
  }
  interface IProps {
    customMapConfig?: {
      center?: [number, number];
      zoom?: number;
    };
    needControls?: boolean;
    controlConfig?: IObject;
    gisHTMLLinkClick?: () => {};
  }

  const props = withDefaults(defineProps<IProps>(), {
    // needControls: true,
    needControls: false,
  });
  // const { proxy } = getCurrentInstance();

  const $L: any = inject('$L');
  // 地图实例
  let mapContainer = ref<any>({});
  let layers = reactive<{ [name: string]: any }>({});

  // 初始化地图
  const initMap = () => {
    mapContainer = $L.map('mapContainer', { ...mapConfig, ...props.customMapConfig });
    // 底图
    $L.tileLayer(mapConfig.baseMap, {
      maxZoom: mapConfig.maxZoom,
    }).addTo(mapContainer);
    if (props.needControls) {
      addControls(props.controlConfig);
    }
  };

  /** (父组件使用)添加散点图层
   * @layerId 图层唯一标识，方便后续清除使用
   * @latLng [经度, 纬度]
   * @data 散点业务数据，暂时还没用上，后续看业务需求，不用的话就去了
   * @option 散点的配置，icon相关，后续逐步明确需要哪些
   * @popupHtml 点击散点后弹出的html元素，内部展示效果完全自定义
   */
  const addPointLayer = (layerId: string | number, latLng: [number, number], data: any, option?: any, popupHtml?: string) => {
    // const iconUrl = require;
    if (!layers[layerId]) {
      const defaultIcon = $L.icon({
        iconUrl: iconUrl,
        iconSize: [30, 30],
        iconAnchor: [15, 25],
        popupAnchor: [0, -30],
      });
      const icon = option?.customIcon || defaultIcon;
      let drawMarker = $L.marker(latLng, { icon }).addTo(mapContainer).bindPopup(generatePopupHtml(latLng, data, popupHtml), {
        minWidth: 200,
      });
      // tips: 后续业务需要手动弹出气泡的话，使用xxxMargker.openPopup()方法，对应closePopup()
      layers[layerId] = drawMarker;
    }
  };

  /** (父组件使用)添加轨迹图层，即根据点位坐标连线
   * @layerId 图层唯一标识，方便后续清除使用
   * @coordinateGroup [[经度, 纬度], [经度, 纬度]]
   * @groupIndex 折线的索引，若没有多条，默认为0（为了区分颜色使用）。
   */
  const addPolylineLayer = (layerId: string | number, coordinateGroup, groupIndex = 0) => {
    // 颜色区分, 如果需要使用到多条线
    const colorDictionary = {
      0: 'rgba(0, 59, 109, 1)',
      1: 'rgba(2, 119, 189, 1)',
      2: 'rgba(43, 144, 248, 1)',
      // 0: {
      //   0: 'rgba(0, 59, 109, 1)',
      //   1: 'rgba(2, 119, 189, 1)',
      //   2: 'rgba(43, 144, 248, 1)',
      // },
      // 1: {
      //   0: 'rgba(8, 130, 107, 1)',
      //   1: 'rgba(0, 198, 188, 1)',
      //   2: 'rgba(134, 222, 126, 1)',
      // },
      // 2: {
      //   0: 'rgba(186, 114, 0, 1)',
      //   1: 'rgba(250, 126, 57, 1)',
      //   2: 'rgba(255, 202, 40, 1)',
      // },
      // 3: {
      //   0: 'rgba(87, 86, 148, 1)',
      //   1: 'rgba(85, 86, 212, 1)',
      //   2: 'rgba(134, 222, 126, 1)',
      // },
    };
    // 使用 Polyline 来连接多个坐标点
    let drawPolyline = $L
      .polyline([...coordinateGroup], {
        color: `${colorDictionary[groupIndex]}`,
        dashArray: '10,10',
        weight: 4,
      })
      .addTo(mapContainer);
    layers[layerId] = drawPolyline;
  };

  // 气泡内容的html
  const generatePopupHtml = (latLng, data, popupHtml) => {
    console.log(latLng, 'latLng');
    const defaultHtml = `
    <div class="map-popup-content">
      坐标信息
      <div class="map-popup-item">
        <span>经度：</span><span>${latLng[1]}</span>
      </div>
      <div class="map-popup-item">
        <span>纬度：</span><span>${latLng[0]}</span>
      </div>
		</div> 
    `;
    return popupHtml || defaultHtml;
  };

  /** (父组件使用)清除地图图层
   * @layerId 图层唯一标识，与添加图层时的id对应
   */
  const clearMapLayer = (layerId) => {
    if (Object.hasOwnProperty.call(layers, layerId)) {
      // mapContainer.removeLayer(layers[layerId]);
      layers[layerId].remove();
      layers[layerId] = null;
    }
  };

  // 添加框选控件
  const addControls = (controlConfig) => {
    const config = {
      position: 'topright',
      drawPolygon: true, // 添加绘制多边形
      drawMarker: true, //添加按钮以绘制标记(地图打点标记)
      drawCircleMarker: true, //添加按钮以绘制圆形标记
      drawPolyline: true, //添加按钮绘制线条
      drawRectangle: true, //添加按钮绘制矩形
      drawCircle: true, //  添加按钮绘制圆圈
      editMode: true, //  添加按钮编辑多边形
      dragMode: true, //   添加按钮拖动多边形
      cutPolygon: true, // 添加一个按钮以删除图层里面的部分内容
      removalMode: true, // 清除图层
      ...controlConfig,
    };
    mapContainer.pm.addControls(config);
    // 设置绘制线条颜色
    mapContainer.pm.setPathOptions({
      color: 'orange',
      fillColor: 'green',
      fillOpacity: 0.4,
    });
    //设置语言  en, de, it, ru, ro, es, fr, pt_br, zh , nl
    mapContainer.pm.setLang('zh');
    getlatLngs();
  };

  /** 手动触发绘制（即 不需要点地图上工具条内的按钮，也可以开始绘制）*/
  const drawPolygon = () => {
    mapContainer.pm.enableDraw('Polygon', {
      snappable: false,
      snapDistance: 10,
    });
  };

  // 获取绘制的坐标
  const getlatLngs = () => {
    //pm:drawstart 开始第一个点的时候调用
    //pm:drawend  禁止绘制时调用
    //pm:create  创建完成时调用
    mapContainer.on('pm:drawstart', (e) => {
      console.log(e, 'first');
    });
    mapContainer.on('pm:drawend', (e) => {
      console.log(e, '禁止绘制');
    });
    mapContainer.on('pm:create', (e) => {
      console.log(e, '绘制完成时调用');
      if (e.shape === 'Marker') {
        console.log(e.layer._latlng, '绘制标记点位');
        // alert("精度:" + e.layer._latlng.lat + ",纬度:" + e.layer._latlng.lng);
      } else {
        console.log(e.layer._latlngs[0], '绘制坐标');
      }
      e.layer.pm.enable({
        allowSelfIntersection: false,
        preventMarkerRemoval: false, // 禁止右键删除点
      });
      e.layer.on('pm:edit', (e) => {
        console.log(e, '拖动');
        console.log(e.target._latlngs[0], '拖动后的坐标');
      });
      e.layer.on('pm:vertexadded', (e) => {
        console.log(e, '添加顶点');
      });
      // e.layer.on("pm:cut", (e) => {
      //   console.log(e, "切割");
      // });
    });
  };
  // 搜索
  // const searchPlace = () => {};

  defineExpose({
    addPointLayer,
    addPolylineLayer,
    clearMapLayer,
    // addControls,
    drawPolygon,
  });

  // 组件挂载2后初始化地图、初始化点击事件
  onMounted(() => {
    initMap();
    if (props.gisHTMLLinkClick) {
      globalThis.gisHTMLLinkClick = (...params) => {
        props.gisHTMLLinkClick!(...params);
      };
    }
  });

  onUnmounted(() => {
    globalThis.gisHTMLLinkClick = {};
  });
</script>

<template>
  <div class="gis">
    <div id="mapContainer" class="map-container" ref="mapContainer"></div>
  </div>
</template>

<style lang="less" scoped>
  .gis {
    // TODO 地图高度由父组件决定
    // height: calc(100vh - 220px);
    height: 100%;
    position: relative;
  }

  .map-container {
    width: 100%;
    // TODO 待删除
    // height: calc(100% - 100px);
    height: 100%;
    overflow: hidden;
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    margin: auto;
    z-index: 2;
  }

  :deep(.leaflet-container) {
    font-size: 16px;
  }
</style>
